using Lzfy_Refund_Service.Models;
using Lzfy_Refund_Service.Repositories;
using TaskStatus = Lzfy_Refund_Service.Models.PasswordTaskStatus;

namespace Lzfy_Refund_Service.Services
{
    /// <summary>
    /// 密码更新后台服务
    /// </summary>
    public class PasswordUpdateBackgroundService : BackgroundService
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly ILogger<PasswordUpdateBackgroundService> _logger;
        private readonly TimeSpan _checkInterval = TimeSpan.FromMinutes(1); // 每分钟检查一次
        private readonly TimeSpan _cleanupInterval = TimeSpan.FromHours(24); // 每24小时清理一次
        private DateTime _lastCleanupTime = DateTime.MinValue;
        
        // 健康状态监控
        private int _consecutiveErrors = 0;
        private DateTime _lastSuccessTime = DateTime.Now;
        private readonly object _statusLock = new object();
        private const int MaxConsecutiveErrors = 5;

        public PasswordUpdateBackgroundService(
            IServiceProvider serviceProvider,
            ILogger<PasswordUpdateBackgroundService> logger)
        {
            _serviceProvider = serviceProvider;
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("密码更新后台服务启动");

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    await ProcessPendingTasksAsync();
                    await CleanupExpiredTasksAsync();
                    
                    // 重置错误计数
                    lock (_statusLock)
                    {
                        _consecutiveErrors = 0;
                        _lastSuccessTime = DateTime.Now;
                    }
                }
                catch (Exception ex)
                {
                    lock (_statusLock)
                    {
                        _consecutiveErrors++;
                    }
                    
                    _logger.LogError(ex, "密码更新后台服务执行异常 (连续错误次数: {ConsecutiveErrors})", _consecutiveErrors);
                    
                    // 如果连续错误次数过多，增加延迟时间
                    if (_consecutiveErrors >= MaxConsecutiveErrors)
                    {
                        _logger.LogWarning("密码更新后台服务连续错误次数达到阈值，将延长检查间隔");
                        await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
                        
                        // 尝试强制垃圾回收
                        GC.Collect();
                        GC.WaitForPendingFinalizers();
                        GC.Collect();
                    }
                }

                try
                {
                    var delayTime = _consecutiveErrors >= MaxConsecutiveErrors ? 
                        TimeSpan.FromMinutes(5) : _checkInterval;
                    await Task.Delay(delayTime, stoppingToken);
                }
                catch (OperationCanceledException)
                {
                    // 正常取消，退出循环
                    break;
                }
            }

            _logger.LogInformation("密码更新后台服务停止");
        }

        /// <summary>
        /// 处理待执行的任务
        /// </summary>
        private async Task ProcessPendingTasksAsync()
        {
            using var scope = _serviceProvider.CreateScope();
            var taskRepository = scope.ServiceProvider.GetRequiredService<IPasswordUpdateTaskRepository>();
            var taskService = scope.ServiceProvider.GetRequiredService<IPasswordUpdateTaskService>();

            try
            {
                var currentTime = DateTime.Now;
                var tasksToExecute = await taskRepository.GetTasksToExecuteAsync(currentTime, 50);

                if (tasksToExecute.Count > 0)
                {
                    _logger.LogInformation("发现 {Count} 个待执行的密码更新任务", tasksToExecute.Count);

                    // 并行执行任务，但限制并发数
                    using var semaphore = new SemaphoreSlim(5, 5); // 最多同时执行5个任务
                    var tasks = tasksToExecute.Select(async task =>
                    {
                        await semaphore.WaitAsync();
                        try
                        {
                            await taskService.ExecuteTaskAsync(task);
                            _logger.LogDebug("任务 {TaskId} 执行成功", task.Id);
                        }
                        catch (Exception taskEx)
                        {
                            _logger.LogError(taskEx, "任务 {TaskId} 执行失败: {Error}", task.Id, taskEx.Message);
                            // 不重新抛出异常，避免影响其他任务
                        }
                        finally
                        {
                            semaphore.Release();
                        }
                    });

                    await Task.WhenAll(tasks);
                    _logger.LogInformation("批次任务处理完成，共处理 {Count} 个任务", tasksToExecute.Count);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理待执行任务时发生异常");
                throw; // 重新抛出异常，让上层处理
            }
        }

        /// <summary>
        /// 清理过期任务
        /// </summary>
        private async Task CleanupExpiredTasksAsync()
        {
            // 检查是否需要清理
            if (DateTime.Now - _lastCleanupTime < _cleanupInterval)
            {
                return;
            }

            using var scope = _serviceProvider.CreateScope();
            var taskRepository = scope.ServiceProvider.GetRequiredService<IPasswordUpdateTaskRepository>();

            try
            {
                // 清理7天前的已完成任务
                var beforeDate = DateTime.Now.AddDays(-7);
                var cleanedCount = await taskRepository.CleanupCompletedTasksAsync(beforeDate);

                if (cleanedCount > 0)
                {
                    _logger.LogInformation("清理了 {Count} 个过期任务", cleanedCount);
                }

                _lastCleanupTime = DateTime.Now;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "清理过期任务时发生异常");
            }
        }

        public override async Task StopAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("正在停止密码更新后台服务...");
            await base.StopAsync(stoppingToken);
        }

        /// <summary>
        /// 获取服务健康状态
        /// </summary>
        public (bool IsHealthy, int ConsecutiveErrors, DateTime LastSuccessTime) GetHealthStatus()
        {
            lock (_statusLock)
            {
                var isHealthy = _consecutiveErrors < MaxConsecutiveErrors && 
                               (DateTime.Now - _lastSuccessTime).TotalMinutes < 10;
                return (isHealthy, _consecutiveErrors, _lastSuccessTime);
            }
        }
    }
}